home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 33
/
Aminet 33 - October 1999.iso
/
Aminet
/
comm
/
misc
/
DigiCam.lha
/
src
/
camera.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-07-15
|
9KB
|
402 lines
/* camera.c (c) 1999 by Volker Remuß, remuss@cs.tu-berlin.de */
#include "machine_amiga.h"
#include "camera.h"
#include "cameraops.h"
#include <stdio.h>
static int32 serialspeed;
void closecamera(void)
{
takeaction(FINISH_SESSION, 0); // Send finish session to camera (sets camera back to 19200)
}
int initcamera(int32 initspeed, int32 communicationspeed, int16 quiet)
{
unsigned char speed;
unsigned char ackbuf[1];
int16 i;
serialspeed = communicationspeed;
switch (communicationspeed)
{
case 9600: speed = 1; break;
case 19200: speed = 2; break;
case 38400: speed = 3; break;
case 57600: speed = 4; break;
case 115200: speed = 5; break;
case 230400: speed = 6; break;
case 460800: speed = 7; break;
default: printf("Serial speed unkown, using 19200 bps\n"); speed = 2; serialspeed = 19200; break; // speed defaults to 19200
}
setlocalserialspeed(initspeed);
buf[0] = 0x00;
writeserial(buf, 1);
delay(20);
ackbuf[0] = 0;
for (i=1; ackbuf[0] != 0x15; i++)
{
delay(5);
readserial(ackbuf, 1, 0);
if (!(i % 4))
{
if (!(quiet)) printf("Calling Camera\n");
writeserial(buf, 1);
}
}
buf [0] = 0x1b; // Commandpacket
buf [1] = 0x53; // First in Session
buf [2] = 0x06; // Datalength = 6
buf [3] = 0x00; // "
buf [4] = 0x00; // 0 Command: set vlaue of int32 register
buf [5] = 17; // Register 17: Set Communication Speed
buf [6] = speed; // data - set communication speed always < 0xff
buf [7] = 0x00; // data
buf [8] = 0x00; // data
buf [9] = 0x00; // data
buf[10] = speed+17; // checkSUM = data(speed) + Register(17) always < 0xff
buf[11] = 0x00;
writeserial(buf, 12);
for (i=0; !readserial(buf, 1, 0); i++)
{
delay(5);
if (i > 50)
{
printf("Camera didn't answer properly ... timeout\n");
return(-1);
}
}
if (buf[0] != 0x06)
{
printf("Speed NOT acknowledged by camera\n");
return (-1);
}
else
if (!(quiet)) printf("Speed acknowledged by camera\n");
delay(5);
setlocalserialspeed(communicationspeed);
delay(25);
return(0);
}
unsigned int16 checksum(unsigned char *srcbuf, int16 length)
{
int16 i;
unsigned int16 sum=0;
for (i=0; i<length; i++)
sum += srcbuf[i];
return(sum);
}
int32 getint32reg(unsigned char reg)
/* Gets the contents of the an int32 register
and directly returns it contents.
Returns -1 in case of failure.
Argument: Number of an int32-register
*/
{
int16 size=0;
unsigned int16 checksum;
checksum = (unsigned int16)reg + 0x01;
buf[0] = 0x1b;
buf[1] = 0x43;
buf[2] = 0x02;
buf[3] = 0x00;
buf[4] = 0x01;
buf[5] = reg;
buf[6] = checksum & 0xff;
buf[7] = (checksum >> 8) & 0xff;
writeserial(buf, 8); // send command
getdatapacket(buf, &size, 0, 0); // get packet, -size. Not interested in sequence.
if (size != 4)
{
//printf("Int32-Register unreadable\n");
return (-1);
}
return (buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24);
}
int16 putint32reg(unsigned char reg, int32 data)
{
unsigned int16 checksum;
unsigned char ackbuf[1];
int16 notacknowledged = 1;
unsigned char data0, data1, data2, data3;
int16 i;
data0 = data & 0xff;
data1 = (data >> 8) & 0xff;
data2 = (data >> 16) & 0xff;
data3 = (data >> 24) & 0xff;
checksum = (unsigned int16)data0 + data1 + data2 + data3 + reg;
buf[0] = 0x1b;
buf[1] = 0x43;
buf[2] = 0x06;
buf[3] = 0x00;
buf[4] = 0x00;
buf[5] = reg;
buf[6] = data0;
buf[7] = data1;
buf[8] = data2;
buf[9] = data3;
buf[10] = checksum & 0xff;
buf[11] = (checksum >> 8) & 0xff;
while (notacknowledged)
{
writeserial(buf, 12);
for (i=0; !readserial(ackbuf, 1, 0); i++)
{
delay(5);
if (i > 50)
{
printf("Timeout in putint32\n");
ackbuf[0] = 0;
break;
}
}
if (ackbuf[0] != 0x06)
{
if (ackbuf[0] == 0x11)
{
printf("Operation denied by camera\n", reg);
return(-1);
}
notacknowledged = 1;
}
else
notacknowledged = 0;
}
return(0);
}
int16 initgetvdatareg(unsigned char reg)
/*
This function sends the command to read a vdata-register. The caller has
to receive the incoming datapackets at his own by calling getdatapacket
for every single packet for a whole sequence of packets.
Interrupting a sequence of datapackets is not supported.
Always returns 0 since there is no other acknowledgment than incoming
datapackets.
Argument: Number of a vdata-register
*/
{
unsigned int16 checksum;
checksum = (unsigned int16)reg + 0x04;
buf[0] = 0x1b; // Command
buf[1] = 0x43; // not the first in session
buf[2] = 0x02; // length = 2;
buf[3] = 0x00; // ""
buf[4] = 0x04; // Command: Read vdata
buf[5] = reg; // which register
buf[6] = checksum & 0xff;
buf[7] = (checksum >> 8) & 0xff;
writeserial(buf, 8); // send command
// command is not acknowledge.
// camera responds with data packages
return (0); // no errorcodes here (yet ?)
}
int16 getdatapacket(unsigned char *destbuf, int16 *datasize, int16 *waslastpacket, int16 *sequencenumber)
/*
getdatapacket retrieve an Datapacket of unknown size.
The given buffer has to be big enough to keep the whole packet.
Size of the packet's dataarea is always returned in datasize
waslastpaket and sequencenumber only returned if pointer != 0
Only data of packet is returned.
*/
{
unsigned char ackbuf[1];
int16 i;
int16 res;
int16 notacknowledged = 1; // needed to enable rereceiving of damaged packets
int16 error;
while(notacknowledged) // loop to re-receive damaged packets
{
for (i = 0; inreadbuffer() < 4; i++) // timeout loop for datapackets needed e.g. when
{ // trying to read write-only registers
delay(1);
if (i > 10) // wait for packetheader (4 byte) or error (1 byte) code
{
if ((res=inreadbuffer()) > 0 && (res < 3)) // maybe camera reports illegal command?
{ // that would be a single 0x11, but since
readserial(ackbuf, 1, 1); // there was some delay camera maybe closed
if (ackbuf[0] == 0x11) // session already (0xff). Therefore < 3
{
printf("Operation denied by camera ");
*datasize = 0;
return(-1);
}
}
printf("Datapaket timed out.\n");
*datasize = 0;
return (-1);
}
}
if (4 != readserial(destbuf, BUFSIZE, 4)) printf("Error while reading datapacket!");
if (waslastpacket)
switch (destbuf[0])
{
case 0x02: *waslastpacket = 0; break; // datapacket
case 0x03: *waslastpacket = 1; break; // lastdatapacket
default: break; //return (-1); // NO datapacket
}
if (sequencenumber) *sequencenumber = (int16) destbuf[1];
*datasize = destbuf[2] | (destbuf[3] << 8);
for (i=0, error = 0; inreadbuffer() != *datasize+2; i++)
{
delay(5);
if (i>(2100+1050)/(serialspeed/100))
{
//printf("timeout data ");
readserial(destbuf, BUFSIZE, 0);
error = 1;
break;
}
}
if (!error)
if (*datasize+2 != readserial(destbuf, BUFSIZE, *datasize+2))
{
printf("Error while reading datapacket!\n");
error=1;
}
if (!error && (checksum(destbuf, *datasize) == (destbuf[*datasize] | (destbuf[*datasize+1] << 8))))
{
ackbuf[0] = 0x06;
notacknowledged = 0;
}
else
{
printf("!");
fflush(stdout);
ackbuf[0] = 0x15;
}
writeserial(ackbuf, 1);
}
}
int16 takeaction(unsigned char action, unsigned char argument)
{
unsigned int16 checksum;
unsigned char ackbuf[2];
int16 notacknowledged = 1;
int16 i;
checksum = (unsigned int16)action + argument + 0x02;
buf[0] = 0x1b;
buf[1] = 0x43;
buf[2] = 0x03;
buf[3] = 0x00;
buf[4] = 0x02;
buf[5] = action;
buf[6] = argument;
buf[7] = checksum & 0xff;
buf[8] = (checksum >> 8) & 0xff;
if (action == FINISH_SESSION)
{
writeserial(buf, 9); // send command
return(0); // FINISH_SESSION is not acknowledged
}
while (notacknowledged)
{
writeserial(buf, 9); // send command
for (i=0; inreadbuffer() == 0; i++)
{
delay(5);
if (i > 100)
{
printf("Timeout Takeaction 1\n");
return(-1);
}
}
readserial(ackbuf, 1, 1);
if (ackbuf[0] == 0x06)
{
//readserial(ackbuf, 1, 1);
for (i=0; !readserial(ackbuf, 1, 0); i++)
{
delay(5);
if (i > 50)
{
printf("Timeout Takeaction 2\n");
ackbuf[0] = 0;
break;
}
}
if (ackbuf[0] == 0x05)
notacknowledged = 0;
else
notacknowledged = 1;
}
else
{
if (ackbuf[0] == 0x11)
{
printf("Action %d denied by camera\n", (int16)action);
return(-1);
}
notacknowledged = 1;
}
}
return(0);
}